package RadianceM.DistributionSystem.utils;

import RadianceM.DistributionSystem.dto.TokenInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @className: JwtUtils
 * @description: JwtUtils工具类
 * @author: 小碗
 * @date: 2023-11-03 18:05:41
 */

@Slf4j
@Component
public class JwtUtils {
	/**
	 * 自定义秘钥
	 * */
	private static String sign;

	/**
	 * jwtToken的默认有效时间 单位分钟
	 * */
	private static int expireTime;

	public static int getExpireTime() {
		return expireTime;
	}

	@Value("${jwt.sign}")
	public void setSign(String sign){
		JwtUtils.sign = sign;
	}

	@Value("${jwt.expireTime}")
	public void setExpireTime(int expireTime){
		JwtUtils.expireTime = expireTime;
	}

	/**
	 * 生成jwt token
	 * @param map  要存放自定义负载信息
	 * */
	public static String createJwtToken(Map<String,Object> map){
		return  Jwts.builder()
				//放入payLoad部分的信息
				.setClaims(map)
				.signWith(SignatureAlgorithm.HS512,sign)
				.compact();
	}

	/**
	 * 生成jwt token
	 * @param tokenInfo  token信息
	 * */
	public static String createJwtToken(TokenInfo tokenInfo){
		return  JwtUtils.createJwtToken(traverseObject(tokenInfo));
	}

	/*
	* 遍历对象
	* */
	public static Map<String,Object> traverseObject(Object object) {
		HashMap<String,Object> map = new HashMap<>();
		try{
			//通过getDeclaredFields()方法获取对象类中的所有属性（含私有）
			Field[] fields = object.getClass().getDeclaredFields();
			for (Field field : fields) {
				//设置允许通过反射访问私有变量
				field.setAccessible(true);
				//获取字段属性名称
				String name = field.getName();
				//获取字段的值
				Object value = field.get(object);
				//其他自定义操作
				map.put(name, value);
			}
			return map;
		}
		catch (Exception e){
			//处理异常
			throw new RuntimeException(e);
		}
	}

	/**
	 * 从令牌中获取数据,就是payLoad部分存放的数据。如果jwt被改，该函数会直接抛出异常
	 * @param token  令牌
	 * */
	public static Claims parseToken(String token){
		return Jwts.parser()
				.setSigningKey(sign)
				.parseClaimsJws(token)
				.getBody();
	}

	/**
	 * 解密jwtToken
	 * @param token  jwtToken
	 * @return TokenInfo 解密体信息
	 * */
	public static TokenInfo decodeJwtToken(String token) {
		Claims claim = parseToken(token);
		if(     claim.get("loginTime")==null ||
				claim.get("expireTime")==null ||
				claim.get("userId")==null ||
				claim.get("userName")==null
		)
		{
			return null;
		}
		return new TokenInfo(
				Long.valueOf(String.valueOf(claim.get("loginTime"))),
				Long.valueOf(String.valueOf(claim.get("expireTime"))),
				Long.valueOf(String.valueOf(claim.get("userId"))),
				String.valueOf(claim.get("userName"))
		);
	}

}
